{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2024-08-20 16:00:57,364 [INFO] hikyuu version: 2.1.1_202408182226_RELEASE_windows_x64 [<module>] (D:\\workspace\\hikyuu\\hikyuu\\__init__.py:97) [hikyuu::hku_info]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2024-08-20 16:00:57.865 [HKU-I] - Using MYSQL BaseInfoDriver (BaseInfoDriver.cpp:58)\n",
      "2024-08-20 16:00:57.883 [HKU-I] - Loading market information... (StockManager.cpp:481)\n",
      "2024-08-20 16:00:57.890 [HKU-I] - Loading stock type information... (StockManager.cpp:494)\n",
      "2024-08-20 16:00:57.897 [HKU-I] - Loading stock information... (StockManager.cpp:409)\n",
      "2024-08-20 16:00:58.045 [HKU-I] - Loading stock weight... (StockManager.cpp:511)\n",
      "2024-08-20 16:00:59.275 [HKU-I] - Loading KData... (StockManager.cpp:134)\n",
      "2024-08-20 16:01:00.831 [HKU-I] - Preloading all day kdata to buffer! (StockManager.cpp:179)\n",
      "2024-08-20 16:01:00.832 [HKU-I] - Preloading all week kdata to buffer! (StockManager.cpp:179)\n",
      "2024-08-20 16:01:00.832 [HKU-I] - Preloading all month kdata to buffer! (StockManager.cpp:179)\n",
      "2024-08-20 16:01:00.902 [HKU-I] - 1.63s Loaded Data. (StockManager.cpp:159)\n",
      "CPU times: total: 625 ms\n",
      "Wall time: 4.01 s\n"
     ]
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "%time from hikyuu.interactive import *"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1 利用 TM 实现简单的记账本\n",
    "\n",
    "TradeManager对象可以理解为一个模拟的交易账户，负责交易的买/卖操作、记录交易记录以及持仓情况，也可以通过修改其买/卖操作的接口实现实盘接入。创建一个模拟交易账户，通常使用快捷创建函数 crtTM。TM对象的基本操作：\n",
    "\n",
    "- buy  买入\n",
    "- sell 卖出\n",
    "- checkin 存入现金\n",
    "- checkout 取出现金\n",
    "\n",
    "可以利用 TM 实现简单的记账本，手工记录自己的操作情况，例如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "TradeManager {\n",
      "  params: params[precision(int): 2, save_action(bool): 1, support_borrow_cash(bool): 0, support_borrow_stock(bool): 0, ],\n",
      "  name: SYS,\n",
      "  init_date: 2017-01-01 00:00:00,\n",
      "  init_cash: 100000.00,\n",
      "  firstDatetime: 2017-01-03 00:00:00,\n",
      "  lastDatetime: 2017-01-03 00:00:00,\n",
      "  TradeCostFunc: TradeCostFunc(TC_Zero, params[]),\n",
      "  current total funds: 100005.00,\n",
      "  current cash: 99089.00,\n",
      "  current market_value: 916.00,\n",
      "  current short_market_value: 0.00,\n",
      "  current base_cash: 100000.00,\n",
      "  current base_asset: 0.00,\n",
      "  current borrow_cash: 0.00,\n",
      "  current borrow_asset: 0.00,\n",
      "  Position: \n",
      "    SZ000001 平安银行 2017-01-03 00:00:00 1854 100.00 911.00 1029.00 118.00 12.95% 0.12%\n",
      "  Short Position: \n",
      "  Borrow Stock: \n",
      "}\n"
     ]
    }
   ],
   "source": [
    "#创建一个初始资金10万元，起始日期2017年1月1日的模拟账户\n",
    "my_tm = crtTM(init_cash=100000, date=Datetime(201701010000))\n",
    "\n",
    "#2017年1月3日以9.11的价格买入100股\n",
    "td = my_tm.buy(Datetime(201701030000), sm['sz000001'], 9.11, 100)\n",
    "\n",
    "#查看当前资金及持仓情况\n",
    "print(my_tm)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>证券名称</th>\n",
       "      <th>买入日期</th>\n",
       "      <th>已持仓天数</th>\n",
       "      <th>持仓数量</th>\n",
       "      <th>投入金额</th>\n",
       "      <th>当前市值</th>\n",
       "      <th>盈亏金额</th>\n",
       "      <th>盈亏比例</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>证券代码</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>SZ000001</th>\n",
       "      <td>平安银行</td>\n",
       "      <td>2017-01-03</td>\n",
       "      <td>1854</td>\n",
       "      <td>100</td>\n",
       "      <td>911.0</td>\n",
       "      <td>1029.0</td>\n",
       "      <td>118.0</td>\n",
       "      <td>12.952799</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "          证券名称       买入日期  已持仓天数  持仓数量   投入金额    当前市值   盈亏金额       盈亏比例\n",
       "证券代码                                                                   \n",
       "SZ000001  平安银行 2017-01-03   1854   100  911.0  1029.0  118.0  12.952799"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#转化为pandas的DataFrame显示当前持仓情况 \n",
    "position = my_tm.get_position_list()\n",
    "position.to_df()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "TradeManager {\n",
       "  params: params[precision(int): 2, save_action(bool): 1, support_borrow_cash(bool): 0, support_borrow_stock(bool): 0, ],\n",
       "  name: SYS,\n",
       "  init_date: 2017-01-01 00:00:00,\n",
       "  init_cash: 100000.00,\n",
       "  firstDatetime: 2017-01-03 00:00:00,\n",
       "  lastDatetime: 2017-02-21 00:00:00,\n",
       "  TradeCostFunc: TradeCostFunc(TC_Zero, params[]),\n",
       "  current total funds: 100049.00,\n",
       "  current cash: 100049.00,\n",
       "  current market_value: 0.00,\n",
       "  current short_market_value: 0.00,\n",
       "  current base_cash: 100000.00,\n",
       "  current base_asset: 0.00,\n",
       "  current borrow_cash: 0.00,\n",
       "  current borrow_asset: 0.00,\n",
       "  Position: \n",
       "  Short Position: \n",
       "  Borrow Stock: \n",
       "}"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#2017年2月21日以9.60的价格卖出100股\n",
    "td = my_tm.sell(Datetime(201702210000), sm['sz000001'], 9.60)\n",
    "\n",
    "my_tm"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2 利用 Excel 查看交易详情\n",
    "\n",
    "使用 tocsv 方法将 TM 的交易记录、当前持仓及已平仓详细情况分别保存为 csv 文件，以便用 Excel 查看详情。\n",
    "\n",
    "tocsv方法参数为一个指定的目录，目录必须以存在。其输出会在指定目录中，生成三个文件，“TM名称_交易记录.csv”、“TM名称_未平仓记录.csv”、“TM名称_已平仓记录.csv”。TM名称可在crtTM创建TM对象时指定，默认为“SYS”，如下图所示。\n",
    "\n",
    "<img src=\"images/008_01_tocsv.png\" align='left'>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "#在 hikyuu_XXX.ini 文件中配置的临时路径中输出\n",
    "my_tm.tocsv(sm.tmpdir())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用 Excel 查看 csv，如：\n",
    "\n",
    "<img src=\"images/008_02_tocsv_look.png\" align=\"left\">"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3 使用序列化保存或重新载入已有TM对象"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "#保存至指定文件\n",
    "from datetime import date\n",
    "filename = \"{}/my_trade/my_trade_record_{}.xml\".format(sm.tmpdir(), date.today());\n",
    "hku_save(my_tm, filename)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "#载入已保存的TM对象\n",
    "#filename = \"{}/my_trade/my_trade_record_{}.xml\".format(sm.tmpdir(), date.today())\n",
    "new_my_tm = hku_load(filename)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用 hku_save 保存的对象，其格式为XML文件，可直接使用 XML 工具或浏览器查看：\n",
    "\n",
    "<img src=\"images/008_03_pickle.png\" align=\"left\">"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 4 使用订单代理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "买入：SZ000001, 价格: 9.33, 数量: 1000.0 预期止损价: 0.0, 预期目标价: nan, 信号来源: SystemPart.SIGNAL\n",
      "卖出：SZ000001, 价格: 9.16, 数量: 1000.0, 信号来源: SystemPart.SIGNAL\n",
      "买入：SZ000001, 价格: 9.33, 数量: 1000.0 预期止损价: 0.0, 预期目标价: nan, 信号来源: SystemPart.SIGNAL\n",
      "卖出：SZ000001, 价格: 10.55, 数量: 1000.0, 信号来源: SystemPart.SIGNAL\n",
      "买入：SZ000001, 价格: 10.56, 数量: 1000.0 预期止损价: 0.0, 预期目标价: nan, 信号来源: SystemPart.SIGNAL\n",
      "卖出：SZ000001, 价格: 10.35, 数量: 1000.0, 信号来源: SystemPart.SIGNAL\n",
      "买入：SZ000001, 价格: 10.56, 数量: 1000.0 预期止损价: 0.0, 预期目标价: nan, 信号来源: SystemPart.SIGNAL\n",
      "卖出：SZ000001, 价格: 10.43, 数量: 1000.0, 信号来源: SystemPart.SIGNAL\n",
      "买入：SZ000001, 价格: 10.58, 数量: 1000.0 预期止损价: 0.0, 预期目标价: nan, 信号来源: SystemPart.SIGNAL\n",
      "卖出：SZ000001, 价格: 11.12, 数量: 1000.0, 信号来源: SystemPart.SIGNAL\n",
      "买入：SZ000001, 价格: 10.4, 数量: 1000.0 预期止损价: 0.0, 预期目标价: nan, 信号来源: SystemPart.SIGNAL\n",
      "卖出：SZ000001, 价格: 9.94, 数量: 1000.0, 信号来源: SystemPart.SIGNAL\n",
      "买入：SZ000001, 价格: 10.31, 数量: 1000.0 预期止损价: 0.0, 预期目标价: nan, 信号来源: SystemPart.SIGNAL\n",
      "卖出：SZ000001, 价格: 10.12, 数量: 1000.0, 信号来源: SystemPart.SIGNAL\n",
      "买入：SZ000001, 价格: 10.22, 数量: 1000.0 预期止损价: 0.0, 预期目标价: nan, 信号来源: SystemPart.SIGNAL\n",
      "卖出：SZ000001, 价格: 10.11, 数量: 1000.0, 信号来源: SystemPart.SIGNAL\n",
      "买入：SZ000001, 价格: 10.13, 数量: 1000.0 预期止损价: 0.0, 预期目标价: nan, 信号来源: SystemPart.SIGNAL\n"
     ]
    }
   ],
   "source": [
    "#创建模拟交易账户进行回测，初始资金30万\n",
    "my_tm = crtTM(init_cash=300000, date=Datetime(201701010000))\n",
    "\n",
    "#注册实盘交易订单代理\n",
    "ob = crtOB(TestOrderBroker())\n",
    "my_tm.reg_broker(ob) #TestOerderBroker是测试用订单代理对象，只打印\n",
    "# 注意：pybind 不支持下面这种方式调用，必须先生成实例再传入！！！\n",
    "# my_tm.reg_broker(crtOB(TestOrderBroker(), False))\n",
    "\n",
    "#根据需要修改订单代理最后的时间戳，后续只有大于该时间戳时，订单代理才会实际发出订单指令\n",
    "my_tm.broker_last_datetime=Datetime(201701010000)\n",
    "\n",
    "#创建信号指示器（以5日EMA为快线，5日EMA自身的10日EMA作为慢线，快线向上穿越慢线时买入，反之卖出）\n",
    "my_sg = SG_Flex(EMA(C, n=5), slow_n=10)\n",
    "\n",
    "#固定每次买入1000股\n",
    "my_mm = MM_FixedCount(1000)\n",
    "\n",
    "#创建交易系统并运行\n",
    "sys = SYS_Simple(tm = my_tm, sg = my_sg, mm = my_mm)\n",
    "sys.run(sm['sz000001'], Query(-150))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
